﻿using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System;

namespace Fast.Extensions.DatabaseAccessor.EntityFrameworkCore
{
    /// <summary>
    /// 非泛型仓储实现
    /// </summary>
    [SkipScan]
    public class Repository : IRepository
    {
        /// <summary>
        /// 服务提供器
        /// </summary>
        private readonly IServiceProvider _serviceProvider;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="serviceProvider">服务提供器</param>
        public Repository(
            IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }

        /// <summary>
        /// 切换仓储
        /// </summary>
        /// <typeparam name="TEntity">实体类型</typeparam>
        /// <returns>仓储</returns>
        public virtual IRepository<TEntity> Change<TEntity>()
            where TEntity : class, IRootEntity, new()
        {
            return _serviceProvider.GetService<IRepository<TEntity>>();
        }

        /// <summary>
        /// 切换多数据库上下文仓储
        /// </summary>
        /// <typeparam name="TEntity">实体类型</typeparam>
        /// <typeparam name="TDbContextLocator">数据库上下文定位器</typeparam>
        /// <returns>仓储</returns>
        public virtual IRepository<TEntity, TDbContextLocator> Change<TEntity, TDbContextLocator>()
            where TEntity : class, IRootEntity, new()
            where TDbContextLocator : class, IDbContextLocator
        {
            return _serviceProvider.GetService<IRepository<TEntity, TDbContextLocator>>();
        }
    }
    /// <summary>
    /// 泛型仓储实现
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    [SkipScan]
    public partial class Repository<TEntity> : Repository<TEntity, DefaultDbContextLocator>, IRepository<TEntity>
        where TEntity : class, IRootEntity, new()
    {
        public Repository(IServiceProvider serviceProvider) : base(serviceProvider)
        {

        }
    }
    /// <summary>
    /// 泛型仓储实现
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    [SkipScan]
    public partial class Repository<TEntity, TDbContextLocator> : RootRepository<TEntity>, IRepository<TEntity, TDbContextLocator>
        where TEntity : class, IRootEntity, new()
        where TDbContextLocator : class, IDbContextLocator
    {
        public Repository(IServiceProvider serviceProvider) : base(serviceProvider, typeof(TDbContextLocator))
        {

        }
    }
    /// <summary>
    /// 根泛型仓储实现
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    [SkipScan]
    public partial class RootRepository<TEntity> : RootSqlRepository, IRootRepository<TEntity>
       where TEntity : class, IRootEntity, new()
    {
        private readonly IRepository _repository;

        public RootRepository(IServiceProvider serviceProvider, Type dbContextLocator)
            : base(serviceProvider, dbContextLocator)
        {
            Entities = Context.Set<TEntity>();

            // 非泛型仓储
            _repository = serviceProvider.GetService<IRepository>();
        }
        /// <summary>
        /// 实体集合
        /// </summary>
        public virtual DbSet<TEntity> Entities { get; }

        /// <summary>
        /// 切换仓储
        /// </summary>
        /// <typeparam name="TChangeEntity">实体类型</typeparam>
        /// <returns>仓储</returns>
        public virtual new IRepository<TChangeEntity> Change<TChangeEntity>()
            where TChangeEntity : class, IRootEntity, new()
        {
            return _repository.Change<TChangeEntity>();
        }

        /// <summary>
        /// 切换多数据库上下文仓储
        /// </summary>
        /// <typeparam name="TChangeEntity">实体类型</typeparam>
        /// <typeparam name="TChangeDbContextLocator">数据库上下文定位器</typeparam>
        /// <returns>仓储</returns>
        public virtual IRepository<TChangeEntity, TChangeDbContextLocator> Change<TChangeEntity, TChangeDbContextLocator>()
            where TChangeEntity : class, IRootEntity, new()
            where TChangeDbContextLocator : class, IDbContextLocator
        {
            return _repository.Change<TChangeEntity, TChangeDbContextLocator>();
        }
    }
}
